package org.rc.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.rc.dto.*;
import org.rc.entity.*;
import org.rc.enums.DevType;
import org.rc.service.*;
import org.rc.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/room")
public class RoomController {

    @Autowired
    RoomService roomService;

    @Autowired
    RoomDevService roomDevService;

    @Autowired
    UserRoomService userRoomService;

    @Autowired
    UserService userService;

    @Autowired
    SxjService sxjService;

    @Autowired
    ShspService shspService;

    @Autowired
    SxzjService sxzjService;

    @Autowired
    MicService micService;

    @Autowired
    SxzjChannelService sxzjChannelService;

    @PutMapping("")
    public Res addRoom(@RequestBody RoomAddDto roomAddDto){
        if(StringUtils.isEmpty(roomAddDto.getName())){
            return Res.failure("请输入房间名称");
        }
        if(!CollectionUtils.isEmpty(roomService.getByRoomName(roomAddDto.getName()))){
            return Res.failure("房间名重复，请重新输入");
        }
        Long roomId = roomService.add(roomAddDto.getName());
        return Res.success(roomId);
    }

    @GetMapping("/info/{id}")
    public Res info(@PathVariable(value = "id") Long id){
        Room room = roomService.getByRoomId(id);
        RoomInfoRes roomInfoRes = new RoomInfoRes();
        roomInfoRes.setId(room.getId());
        roomInfoRes.setName(room.getName());
        UserRoom userRoom = userRoomService.getBindRecordByRoomId(room.getId());
        if(null != userRoom){
            roomInfoRes.setUserId(userRoom.getUserId());
            roomInfoRes.setUserName(userService.getByUserId(userRoom.getUserId()).getName());
        }
        List<RoomDev> roomDevs = roomDevService.getDevsByRoomId(room.getId());
        if(!CollectionUtils.isEmpty(roomDevs)){
            Map<Integer,List<RoomDev>> roomDevMap =  roomDevs.stream().collect(Collectors.groupingBy(RoomDev :: getDevType));
            List<RoomDev> sxjs = roomDevMap.get(DevType.SXJ.getType());
            List<RoomDev> sxzjs = roomDevMap.get(DevType.XSZJ.getType());
            List<RoomDev> slps = roomDevMap.get(DevType.SLP.getType());
            List<RoomDev> shsps = roomDevMap.get(DevType.SHSP.getType());
            List<RoomDev> mics = roomDevMap.get(DevType.MIC.getType());
            if(!CollectionUtils.isEmpty(sxjs)){
                roomInfoRes.setCameraIds(sxjs.stream().map(RoomDev ::getDevId).collect(Collectors.toList()));
            }
            if(!CollectionUtils.isEmpty(sxzjs)){
                roomInfoRes.setSxIds(sxzjs.stream().map(RoomDev ::getDevId).collect(Collectors.toList()));
            }
            if(!CollectionUtils.isEmpty(slps)){
                roomInfoRes.setSlIds(slps.stream().map(RoomDev ::getDevId).collect(Collectors.toList()));
            }
            if(!CollectionUtils.isEmpty(shsps)){
                roomInfoRes.setShIds(shsps.stream().map(RoomDev ::getDevId).collect(Collectors.toList()));
            }
            if(!CollectionUtils.isEmpty(mics)){
                roomInfoRes.setMics(mics.stream().map(RoomDev ::getDevId).collect(Collectors.toList()));
            }
        }
        return Res.success(roomInfoRes);
    }

    @PostMapping("")
    public Res updateRoom(@RequestBody RoomUpdateDto roomUpdateDto){
        if(StringUtils.isEmpty(roomUpdateDto.getName())){
            return Res.failure("请输入房间名称");
        }
        if(!CollectionUtils.isEmpty(roomService.getByRoomName(roomUpdateDto.getName(),roomUpdateDto.getRoomId()))){
            return Res.failure("房间名重复，请重新输入");
        }
        Room room = new Room();
        room.setId(roomUpdateDto.getRoomId());
        room.setName(roomUpdateDto.getName());
        roomService.updateRoom(room);
        return Res.success();
    }
    @PutMapping("/dev")
    public Res devBindRoom(@RequestBody DevBindRoomDto devBindRoomDto){
        Long roomId = devBindRoomDto.getId();
        roomDevService.deleteRoomDevs(roomId);
        List<RoomDev> roomDevs = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(devBindRoomDto.getCameraIds())){
            roomDevs.addAll(devBindRoomDto.getCameraIds().stream().map(id-> RoomDev.getInstance(roomId, DevType.SXJ.getType(),id)).collect(Collectors.toList()));
        }
        if(CollectionUtil.isNotEmpty(devBindRoomDto.getSxIds())){
            roomDevs.addAll(devBindRoomDto.getSxIds().stream().map(id-> RoomDev.getInstance(roomId, DevType.XSZJ.getType(),id)).collect(Collectors.toList()));
        }
        if(CollectionUtil.isNotEmpty(devBindRoomDto.getSlIds())){
            roomDevs.addAll(devBindRoomDto.getSlIds().stream().map(id-> RoomDev.getInstance(roomId, DevType.SLP.getType(),id)).collect(Collectors.toList()));
        }
        if(CollectionUtil.isNotEmpty(devBindRoomDto.getShIds())){
            roomDevs.addAll(devBindRoomDto.getShIds().stream().map(id-> RoomDev.getInstance(roomId, DevType.SHSP.getType(),id)).collect(Collectors.toList()));
        }
        if(CollectionUtil.isNotEmpty(devBindRoomDto.getMics())){
            roomDevs.addAll(devBindRoomDto.getMics().stream().map(id-> RoomDev.getInstance(roomId, DevType.MIC.getType(),id)).collect(Collectors.toList()));
        }
        if(CollectionUtil.isNotEmpty(roomDevs)){
            roomDevService.addRoomDevs(roomDevs);
        }
        return Res.success();
    }

    @PutMapping("/user")
    public Res userBindRoom(@RequestBody UserBindRoomDto userBindRoomDto){
        Long roomId = userBindRoomDto.getRoomId();
        Long bindUserId = userBindRoomDto.getBindUser();
        UserRoom userRoom = userRoomService.getBindRecordByRoomId(roomId);
        //没有勾选用户
        if(null == bindUserId){
            //当前绑定关系不为空，说明是解绑
            if(null!=userRoom){
                userRoom.setUnbindTime(LocalDateTime.now());
                userRoomService.updateUserRoom(userRoom);
            }
            return Res.success();
        }
        //勾选了用户，当前绑定关系为空，新建绑定关系
        if(null ==userRoom){
            UserRoom newUserRoom = new UserRoom();
            newUserRoom.setUserId(bindUserId);
            newUserRoom.setRoomId(roomId);
            newUserRoom.setBindTime(LocalDateTime.now());
            userRoomService.addUserRoom(newUserRoom);
        }else{
            //勾选用户和当前绑定的用户相同，不做处理
            if(Objects.equals(userRoom.getUserId(), userBindRoomDto.getBindUser())){
                return Res.success();
            }else{
                //勾选用户和当前绑定的用户不同，先解绑当前绑定的用户，再添加新绑定关系
                userRoom.setUnbindTime(LocalDateTime.now());
                userRoomService.updateUserRoom(userRoom);
                UserRoom newUserRoom = new UserRoom();
                newUserRoom.setUserId(bindUserId);
                newUserRoom.setRoomId(roomId);
                newUserRoom.setBindTime(LocalDateTime.now());
                userRoomService.addUserRoom(newUserRoom);
            }
        }
        return Res.success();
    }

    @DeleteMapping("/{roomId}")
    public Res deleteRoom(@PathVariable(value = "roomId") Long roomId){
        roomService.deleteRoom(roomId);
        List<UserRoom> userRooms = userRoomService.getBindRoomUserByRoomIds(Arrays.asList(roomId));
        LocalDateTime unbindTime = LocalDateTime.now();
        userRooms.forEach(userRoom -> userRoom.setUnbindTime(unbindTime));
        userRoomService.updateBatch(userRooms);
        roomDevService.deleteRoomDevs(roomId);
        return Res.success();
    }

    @PostMapping("/page")
    public Res getRoomPage(@RequestBody RoomPageDto roomPageDto){
        Page<Room> roomPage = roomService.getRoomPage(roomPageDto);
        List<Room> rooms = roomPage.getRecords();
        Map<Long,UserRoom> userRoomMap = null;
        Map<Long,User> userMap = null;
        List<RoomPageRes> roomPageResList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(rooms)){
            List<Long> roomIds = rooms.stream().map(Room :: getId).collect(Collectors.toList());
            List<UserRoom> userRooms = userRoomService.getBindingRoomsByRoomIds(roomIds);
            if(!CollectionUtils.isEmpty(userRooms)){
                userRoomMap = userRooms.stream().collect(Collectors.toMap(UserRoom:: getRoomId, userRoom->userRoom,(exist,replce)->replce));
                List<User> users = userService.getUsersByUserIds(userRooms.stream().map(UserRoom :: getUserId).collect(Collectors.toList()));
                userMap = users.stream().collect(Collectors.toMap(User:: getId, user->user));
            }
            List<RoomDev> roomDevs = roomDevService.getByRoomIds(roomIds);
            for(Room room : rooms){
                RoomPageRes roomPageRes = RoomPageRes.getInstance(room);
                if(!CollectionUtils.isEmpty(roomDevs)){
                    Map<Long,List<RoomDev>> roomDevsMap = roomDevs.stream().collect(Collectors.groupingBy(RoomDev :: getRoomId));
                    if(roomDevsMap.containsKey(room.getId())){
                        List<RoomDev> devs = roomDevsMap.get(room.getId());
                        List<Integer> types = devs.stream().map(RoomDev::getDevType).distinct().collect(Collectors.toList());
                        roomPageRes.setDevTypes(types.stream().map(DevType :: getNameByType).collect(Collectors.toList()));
                    }
                }
                if(!CollectionUtils.isEmpty(userRoomMap) && userRoomMap.containsKey(room.getId())){
                    UserRoom userRoom = userRoomMap.get(room.getId());
                    Long userId = userRoom.getUserId();
                    if(userMap.containsKey(userId)){
                        roomPageRes.setUserName(userMap.get(userId).getName());
                    }
                }
                roomPageResList.add(roomPageRes);
            }
        }
        PageDto pageDto = PageDto.of(roomPage);
        pageDto.setData(roomPageResList);
        return Res.success(pageDto);
    }

    @DeleteMapping("")
    public Res deleteRooms(@RequestBody RoomsDeleteDto roomsDeleteDto){
        roomService.deleteRooms(roomsDeleteDto.getIds());
        List<UserRoom> userRooms = userRoomService.getBindRoomUserByRoomIds(roomsDeleteDto.getIds());
        LocalDateTime unbindTime = LocalDateTime.now();
        userRooms.forEach(userRoom -> userRoom.setUnbindTime(unbindTime));
        userRoomService.updateBatch(userRooms);
        roomDevService.deleteRoomsDev(roomsDeleteDto.getIds());
        return Res.success();
    }

    @GetMapping("/user/{userId}")
    public Res getBindRoomByUserId(@PathVariable(value = "userId") Long id){
        List<UserRoom> userRooms = userRoomService.getRoomsByUserId(id);
        List<Room> rooms = new ArrayList<>();
        if(!CollectionUtils.isEmpty(userRooms)){
            rooms = roomService.getByRoomIds(userRooms.stream().map(UserRoom :: getRoomId).collect(Collectors.toList()));
        }
        return Res.success(rooms);
    }

    @GetMapping("/dev/{roomId}")
    public Res getBindDevByRoomId(@PathVariable(value = "roomId") Long roomId){
        RoomBindSxjAndShspRes roomBindSxjAndShspRes = new RoomBindSxjAndShspRes();
        roomBindSxjAndShspRes.setRoomId(roomId);
        List<RoomDev> roomSxjs = roomDevService.getRoomDevByRoomIdAndDevId(DevType.SXJ.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomSxjs)){
            roomBindSxjAndShspRes.setSxjs(sxjService.getSxjsByIds(roomSxjs.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        List<RoomDev> roomShsps = roomDevService.getRoomDevByRoomIdAndDevId(DevType.SHSP.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomShsps)){
            roomBindSxjAndShspRes.setShsps(shspService.getShspsByIds(roomShsps.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        List<RoomDev> roomSxzjs = roomDevService.getRoomDevByRoomIdAndDevId(DevType.XSZJ.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomSxzjs)){
            roomBindSxjAndShspRes.setSxzjs(sxzjService.getSxzjByIds(roomSxzjs.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        List<RoomDev> roomMics = roomDevService.getRoomDevByRoomIdAndDevId(DevType.MIC.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomMics)){
            roomBindSxjAndShspRes.setMics(micService.getByMicIds(roomMics.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        return Res.success(roomBindSxjAndShspRes);
    }

    @GetMapping("/dev/sxj_sxzj/{roomId}")
    public Res getBindSxjAndSxzjByRoomId(@PathVariable(value = "roomId") Long roomId){
        RoomBindSxjAndShspRes roomBindSxjAndShspRes = new RoomBindSxjAndShspRes();
        roomBindSxjAndShspRes.setRoomId(roomId);
        List<RoomDev> roomSxjs = roomDevService.getRoomDevByRoomIdAndDevId(DevType.SXJ.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomSxjs)){
            roomBindSxjAndShspRes.setSxjs(sxjService.getSxjsByIds(roomSxjs.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        List<RoomDev> roomSxzjs = roomDevService.getRoomDevByRoomIdAndDevId(DevType.XSZJ.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomSxzjs)){
            roomBindSxjAndShspRes.setSxzjs(sxzjService.getSxzjByIds(roomSxzjs.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        return Res.success(roomBindSxjAndShspRes);
    }

    @GetMapping("/dev/shsp_sxzj/{roomId}")
    public Res getShshAndSxzj(@PathVariable(value = "roomId") Long roomId){
        RoomBindSxzjAndShspRes roomBindSxzjAndShspRes = new RoomBindSxzjAndShspRes();
        List<RoomDev> roomShsps = roomDevService.getRoomDevByRoomIdAndDevId(DevType.SHSP.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomShsps)){
            roomBindSxzjAndShspRes.setShsps(shspService.getShspsByIds(roomShsps.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        List<RoomDev> roomMics = roomDevService.getRoomDevByRoomIdAndDevId(DevType.MIC.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomMics)){
            roomBindSxzjAndShspRes.setMics(micService.getByMicIds(roomMics.stream().map(RoomDev :: getDevId).collect(Collectors.toList())));
        }
        List<RoomDev> roomSxzjs = roomDevService.getRoomDevByRoomIdAndDevId(DevType.XSZJ.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomSxzjs)){
            roomSxzjs.forEach(roomSxzj->{
                Sxzj sxzj = sxzjService.getSxzjById(roomSxzj.getDevId());
                List<SxzjChannel> sxzjChannelList = sxzjChannelService.sxzjChannels(sxzj.getId());
                if(!CollectionUtils.isEmpty(sxzjChannelList)){
                    roomBindSxzjAndShspRes.setSxzjChannels(sxzjChannelList.stream().map(sxzjChannel-> RoomBindSxzjAndShspRes.SxzjChannelRes.getInstance(sxzj,sxzjChannel)).collect(Collectors.toList()));
                }
            });
        }
        return Res.success(roomBindSxzjAndShspRes);
    }

    @GetMapping("/dev/sxzj/{roomId}")
    public Res getBindSxzjByRoomId(@PathVariable(value = "roomId") Long roomId){
        List<Sxzj> sxzjs = new ArrayList<>();
        List<RoomDev> roomSxzjs = roomDevService.getRoomDevByRoomIdAndDevId(DevType.XSZJ.getType(), roomId);
        if(!CollectionUtils.isEmpty(roomSxzjs)){
            sxzjs = sxzjService.getSxzjByIds(roomSxzjs.stream().map(RoomDev :: getDevId).collect(Collectors.toList()));
        }
        return Res.success(sxzjs);
    }

    @GetMapping("/{userId}")
    public Res getAllRoomsByUserId(@PathVariable(value = "userId") Long userId){
        User user = userService.getByUserId(userId);
        List<Room> rooms = new ArrayList<>();
        if(1==user.getIsAdmin()){
            rooms = roomService.getAllRooms();
        }else{
            List<UserRoom> userRooms = userRoomService.getAllRoomsByUserId(userId);
            if(!CollectionUtils.isEmpty(userRooms)){
                rooms = roomService.getByRoomIds(userRooms.stream().map(UserRoom ::getRoomId).collect(Collectors.toList()));
            }
        }
        return Res.success(rooms);
    }

    @PostMapping("/user/time_range")
    public Res roomReplayDto(@RequestBody RoomReplayDto roomReplayDto){
        Long roomId = roomReplayDto.getRoomId();
        Long userId = roomReplayDto.getUserId();
        String beginTime = roomReplayDto.getBeginTime();
        String endTime = roomReplayDto.getEndTime();
        if(null == roomId){
            return Res.failure("请选择房间");
        }

        if(null == userId){
            return Res.failure("请选择用户");
        }
        if(StringUtils.isEmpty(beginTime)){
            return Res.failure("请选择开始时间");
        }
        if(StringUtils.isEmpty(endTime)){
            return Res.failure("请选择结束时间");
        }

        LocalDateTime bgDate = DateUtil.string2LocalDateTime(beginTime);
        LocalDateTime edDate = DateUtil.string2LocalDateTime(endTime);

        User user = userService.getByUserId(userId);
        if(1==user.getIsAdmin()){
            return Res.success(true);
        }
        List<UserRoom> userRooms = userRoomService.getUserRoomByCondition(roomId,userId);
        if(CollectionUtils.isEmpty(userRooms)){
            return Res.success(false);
        }
        for(UserRoom userRoom : userRooms){
            LocalDateTime bindTime = userRoom.getBindTime();
            LocalDateTime unbindTime = userRoom.getUnbindTime();
            if(bgDate.isAfter(bindTime) && ( null == unbindTime || edDate.isBefore(unbindTime))){
                return Res.success(true);
            }
        }
        return Res.success(false);
    }

}
